/*Copyright (C) 2009 - 2011 MASSART GAUTHIER

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "../headers.h"

/* Menu principal de l'éditeur de niveaux
*/
void snake_menu_level_editor() {
	int choix;

	do {
		clear();
		choix = afficher_menu_jeu("Créer un niveau dans un pack existant\n"
															"Editer un niveau existant\n"
															"Editer la liste des packs\n"
															"Retour\n",
															TITRE_SNAKE);

		if(choix == 1) {
			snake_create_level();
		}
		else if(choix == 2) {
			snake_choose_level_pack_to_edit();
		}
		else if(choix == 3) {
			edit_level_pack("Snake");
		}
	}
	while(choix != 4);
}

void snake_create_level() {
	SNAKE_CASE_T matrix[SNAKE_MAT_X][SNAKE_MAT_Y];
	char author_name[50], lvl_name[50];
	char root_pack_filename[300], new_pack_filename[256];
	int choix;
	bool loop = true;

	snake_init_to_default(matrix);

	if(snake_level_editor(matrix)) {
		snake_edit_level_info(lvl_name, author_name, 50);

		while(loop == true) {
			clear();
			afficher_titre(TITRE_SNAKE);
			CSLP_ColorText(CT);
			addstr("\n\n Entrez le nom du pack de niveaux où sauvegarder le niveau : ");
			lire(new_pack_filename, 256);

			sprintf(root_pack_filename, "%s%s%s", PACKS_PERSO_ROOT, new_pack_filename, ".pak");

			if(fichier_existe(root_pack_filename) == false) {
				clear();
				choix = afficher_menu("Oui\nNon\n", "Ce pack de niveaux n'existe pas, le créer?\n", TITRE_SNAKE);

				if(choix == 1) {
					if(!add_pack_auto("Snake", new_pack_filename)) {
						CSLP_ColorText(COLOR_GREEN);
						addstr("\n\n La création du pack à réussi.");
						loop = false;
						getch();
					}
				}
			}
			else {
				loop = false;
			}
		}

		if(snake_append_to_lvl_pack(root_pack_filename, matrix, lvl_name, author_name)) {
			addstr("\n\n La sauvegarde a échoué.");
			getch();
		}
		else {
			CSLP_ColorText(COLOR_GREEN);
			addstr("\n\n Niveau sauvegardé avec succès.");
			getch();
		}
	}
}

/* Permet de choisir le pack de niveaux à éditer
*/
void snake_choose_level_pack_to_edit() {
	char root_pack_filename[300];

	if(!choose_pack("Snake", root_pack_filename)) {
		CSLP_ColorText(COLOR_GREEN);
		addstr("\n\n Le pack a bien était chargé.");
		getch();
	}

	snake_choose_level_to_edit(root_pack_filename);
}

/* Permet de choisir le niveau à éditer
*/
void snake_choose_level_to_edit(char *filename) {
	SNAKE_CASE_T matrix[SNAKE_MAT_X][SNAKE_MAT_Y];
	int choix, nb_levels, i = 0;
	char level[1000][50] = {{0}}, author[1000][100] = {{0}}, level_list[50000], lvl_name[50], author_name[100], transfert[100];

	nb_levels = get_level_list(filename, level, author);

	if(!nb_levels) {
		CSLP_ColorText(COL_ERREUR);
		addstr("\n\n Le format du fichier est invalide ou le pack est vide.");
		return;
	}

	while(i != nb_levels) {
		sprintf(transfert, "%s\n", level[i]);
		strcat(level_list, transfert);
		i++;
	}

	strcat(level_list, "Retour\n");
	clear();
	choix = afficher_menu(level_list, "Choisissez le niveau à éditer :", TITRE_SNAKE);

	if(choix <= nb_levels) {
		snake_init_to_default(matrix);

		if(snake_parse_file(filename, level, choix - 1, matrix)) {
			CSLP_ColorText(COL_ERREUR);
			addstr("\n Erreur : Le format du niveau est invalide.");
		}
		else {
			if(snake_level_editor(matrix)) {
				clear();
				snake_edit_level_info(lvl_name, author_name, 50);
				snake_save_level(filename, matrix, author_name, lvl_name);
			}
		}
	}
}

int snake_level_editor(SNAKE_CASE_T matrix[SNAKE_MAT_X][SNAKE_MAT_Y]) {
	bool loop = true;
	int key, choix, retval = 0;
	IPoint cursor_pos;

	curs_set(0);
	snake_display_editor(matrix);
	cursor_pos.x = 1;
	cursor_pos.y = 1;
	move(cursor_pos.y + SNAKE_MAT_ORG_Y, cursor_pos.x + SNAKE_MAT_ORG_X);
	curs_set(1);
	refresh();

	while(loop) {
		key = getch();

		if(key == SNAKE_KEY_QUIT) {
			clear();
			choix = afficher_menu("Sauvegarder et quitter\n"
			"Quitter sans sauvegarder\n"
			"Annuler\n",
			"Que voulez-vous faire?\n",
			TITRE_SNAKE);

			if(choix == 1) {
				loop = false;
				retval = 1;
			}
			else if(choix == 2) {
				loop = false;
				retval = 0;
			}
			else {
				snake_display_editor(matrix);
				curs_set(1);
			}
		}
		else if(key == touche_haut || key == touche_bas || key == touche_droite || key == touche_gauche) {
			snake_move_cursor(key, &cursor_pos);
		}
		else {
			snake_edit_matrix(matrix, key, &cursor_pos);
		}
	}

	curs_set(0);
	return retval;
}

void snake_edit_level_info(char *lvl_name, char *author_name, size_t len) {
	bool loop = true;

	clear();
	afficher_titre(TITRE_SNAKE);
	CSLP_ColorText(CT);
	addstr(" Entrez le nom de l'auteur du niveau :\n");
	get_player_name(0, prenom);
	strcpy(author_name, prenom);
	addstr("\n\n");

	while(loop == true) {
		clear_line();
		addstr(" Entrez le nom du niveau : ");
		lire(lvl_name, len);

		if(lvl_name[0] != '\0') {
			loop = false;
		}
	}
}

int snake_append_to_lvl_pack(char *lvl_pack_filename, SNAKE_CASE_T matrix[SNAKE_MAT_X][SNAKE_MAT_Y], const char *lvl_name, const char *author_name) {

	if(!fichier_existe(lvl_pack_filename)) {
		CSLP_ColorText(COL_ERREUR);
		addstr("\n Le pack de niveaux n'a pas pu être ouvert.");
		return 1;
	}

	snake_save_level(lvl_pack_filename, matrix, author_name, lvl_name);
	return 0;
}

/* Permet de modifier la position du curseur sous ordre
** du joueur
*/
void snake_move_cursor(int key, IPoint *cursor_pos) {
	if(key == touche_bas) {
		if(cursor_pos->y < SNAKE_MAT_Y - 2) {
			cursor_pos->y++;
		}
	}
	else if(key == touche_haut) {
		if(cursor_pos->y > 1) {
			cursor_pos->y--;
		}
	}
	else if(key == touche_droite) {
		if(cursor_pos->x < SNAKE_MAT_X - 2) {
			cursor_pos->x++;
		}
	}
	else if(key == touche_gauche) {
		if(cursor_pos->x > 1) {
			cursor_pos->x--;
		}
	}

	move(cursor_pos->y + SNAKE_MAT_ORG_Y, cursor_pos->x + SNAKE_MAT_ORG_X);
}

/* Permet d'éditer la matrice sous ordre du joueur
*/
void snake_edit_matrix(SNAKE_CASE_T matrix[SNAKE_MAT_X][SNAKE_MAT_Y], int key, IPoint *cursor_pos) {
	SNAKE_CASE_T *cel;

	cel = &matrix[cursor_pos->x][cursor_pos->y];

	if(key == SNAKE_KEY_EMUR) {
		if(*cel != SNAKE_IMPLACABLE) {
			*cel = SNAKE_MUR;
		}

	}
	else if(key == SNAKE_KEY_EVIDE) {
		if(*cel != SNAKE_IMPLACABLE) {
			*cel = SNAKE_VIDE;
		}

	}
	else {
		return;
	}

	snake_refresh_case(NULL, *cel);
	curs_set(0);
	snake_move_cursor(key, cursor_pos);
	curs_set(1);
}

/*Charge le niveau grace au numérot du niveau, au nom du pack et place les info dans matrice, nom_niveau et nom_auteur
*/
int snake_charger_niveau(long niveau, char *filename, char matrice[1000], char nom_niveau[50], char nom_auteur[100]) {
	SNAKE_CASE_T matrix[SNAKE_MAT_X][SNAKE_MAT_Y];
	char level[1000][50] = {{0}}, author[1000][100] = {{0}};
	long nb_level = 0, x = 0, y = 0, i = 0;

	nb_level = get_level_list(filename, level, author);

	if(nb_level != 0) {
		if(niveau > nb_level) {
			niveau = nb_level;
		}

		snake_init_to_default(matrix);
		snake_parse_file(filename, level, niveau, matrix);

		strcpy(nom_niveau, level[niveau]);
		strcpy(nom_auteur, author[niveau]);

		for(y = 0; y < SNAKE_MAT_Y; y++) {
			for(x = 0; x < SNAKE_MAT_X; x++) {
				switch(matrix[x][y]) {
				case SNAKE_VIDE:
					matrice[i] = SNAKE_FVIDE;
					break;
				case SNAKE_MUR:
					matrice[i] = SNAKE_FMUR;
					break;
				case SNAKE_IMPLACABLE:
					matrice[i] = SNAKE_FVIDE;
					break;
				default:
					Log_full(LOG_SNAKE , "snake_save_level : Type de case inconnu", matrix[x][y]);
					matrice[i] = SNAKE_FVIDE;
					break;
				}

				i++;
			}
		}
	}

	return nb_level;
}

int snake_parse_file(char *filename, char level[1000][50], int choix, SNAKE_CASE_T matrix[SNAKE_MAT_X][SNAKE_MAT_Y]) {
	int x, y, numero_ligne = 0;
	char nom_ligne[10], buffer[100], level_name[100];

	sprintf(level_name, "%s", level[choix]);

	/* parsage du niveau */
	for(y = 0; y < SNAKE_MAT_Y; y++) {

		remove_ret_line(buffer);

		numero_ligne++;
		sprintf(nom_ligne, "ligne%d", numero_ligne);

		ini_gets(level_name, nom_ligne, "aap", buffer, sizearray(buffer), filename);

		for(x = 0; x < SNAKE_MAT_X; x++) {
			switch(buffer[x]) {
			case SNAKE_FMUR:
				matrix[x][y] = SNAKE_MUR;
				break;
			case SNAKE_FVIDE:
				matrix[x][y] = SNAKE_VIDE;
				break;
			default:
				matrix[x][y] = SNAKE_MUR;
				break;
			}
		}
	}


	return 0;
}

void snake_save_level(char *level_file, SNAKE_CASE_T matrix[SNAKE_MAT_X][SNAKE_MAT_Y], const char *author_name, const char *level_name) {
	int x, y, numero_ligne = 0;
	char nom_ligne[10];
	char buffer[64];

	ini_puts(level_name, "auteur", author_name, level_file);

	for(y = 0; y < SNAKE_MAT_Y; y++) {
		remove_ret_line(buffer);

		numero_ligne++;
		sprintf(nom_ligne, "ligne%d", numero_ligne);

		for(x = 0; x < SNAKE_MAT_X; x++) {
			switch(matrix[x][y]) {
			case SNAKE_VIDE:
				buffer[x] = SNAKE_FVIDE;
				break;
			case SNAKE_MUR:
				buffer[x] = SNAKE_FMUR;
				break;
			case SNAKE_IMPLACABLE:
				buffer[x] = SNAKE_FVIDE;
				break;
			default:
				Log_full(LOG_SNAKE , "snake_save_level : Type de case inconnu", matrix[x][y]);
				buffer[x] = SNAKE_FVIDE;
				break;
			}

			ini_puts(level_name, nom_ligne, buffer, level_file);
		}
	}
}

void snake_init_to_default(SNAKE_CASE_T matrix[SNAKE_MAT_X][SNAKE_MAT_Y]) {
	int x, y;

	for(y = 0; y < SNAKE_MAT_Y; y++) {
		for(x = 0; x < SNAKE_MAT_X; x++) {
			if(y == 0 || y == SNAKE_MAT_Y - 1 || x == 0 || x == SNAKE_MAT_X - 1) {
				matrix[x][y] = SNAKE_MUR;
			}
			else if((y == SNAKE_MAT_Y / 2 && ((x >= 1 && x <= 5) || (x >= 47 && x <= 49))) || ((y == SNAKE_MAT_Y / 2 + 1 || y == SNAKE_MAT_Y / 2 - 1) && ((x >= 1 && x <= 4) || (x >= 48 && x <= 49))) || ((y == SNAKE_MAT_Y / 2 + 2 || y == SNAKE_MAT_Y / 2 - 2) && ((x >= 1 && x <= 3) || (x >= 48 && x <= 49)))) {
				matrix[x][y] = SNAKE_IMPLACABLE;
			}
			else {
				matrix[x][y] = SNAKE_VIDE;
			}
		}
	}
}


